home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / gnu / gchess40.lha / gnuchess4.0p62 / src / gnuan.c < prev    next >
C/C++ Source or Header  |  1993-06-22  |  29KB  |  1,278 lines

  1. /*
  2.  * gnuan.c - Analysis interface for gnuchess.
  3.  *
  4.  * Copyright (c) 1988,1989,1990 John Stanback
  5.  * Copyright (c) 1992 Free Software Foundation
  6.  *
  7.  * This file is part of GNU CHESS.
  8.  *
  9.  * GNU Chess is free software; you can redistribute it and/or modify
  10.  * it under the terms of the GNU General Public License as published by
  11.  * the Free Software Foundation; either version 2, or (at your option)
  12.  * any later version.
  13.  *
  14.  * GNU Chess is distributed in the hope that it will be useful,
  15.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  * GNU General Public License for more details.
  18.  *
  19.  * You should have received a copy of the GNU General Public License
  20.  * along with GNU Chess; see the file COPYING.  If not, write to
  21.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  22.  */
  23.  
  24. /*
  25.  * This is a front end for a chess analysis program.  It takes a file of
  26.  * moves in algebraic notation and creates a file containing each move that
  27.  * was made, the move it would have made, the score it would give itself
  28.  * after making the move it recommended, and the depth it searched for the
  29.  * move.
  30.  *
  31.  * This is a modification of nondsp.c.  I have cut out code that was not needed
  32.  * for this application such as the help and edit functions.  Most of the
  33.  * modifications were done in InputCommand.
  34.  */
  35.  
  36. /*
  37.  * This file will generate two different analysis programs.  One is meant to
  38.  * be run as a background process inwhich the in and out files are
  39.  * predefined. The other is meant to be run in the foreground where it will
  40.  * prompt you for the name of the file with the game in it, the maximum depth
  41.  * the search should be conducted to and the time limit per move.  It would
  42.  * be nice to be able to give these parameters on the command line, but that
  43.  * would mean changing main which is in the gnuchess.c file.
  44.  *
  45.  * For each move it will analyse the move until either it has run out of time or
  46.  * it has reached the maximum depth.
  47.  *
  48.  * To build the version for background processing define BACKGROUND_ANALYSIS
  49.  * either at the top of this file, or in compilation.  The files and depth
  50.  * used are defined below.  They are MAX_DEPTH, MAX_TIME, OUT_FILE, IN_FILE
  51.  * and PROG_FILE.  The PROG_FILE is a file that will be updated as each move
  52.  * is analysed so you can check its progress.  This is only updated when
  53.  * running the BACKGROUND_ANALYSIS version.  In the version where the
  54.  * filename and depth are entered at runtime, the output goes to stdout.
  55.  */
  56.  
  57. /*#define BACKGROUND_ANALYSIS 0*/
  58.  
  59. #define MAX_DEPTH  MAXDEPTH
  60. #define MAX_TIME   10 
  61. #define OUT_FILE   "gnuan.out"
  62. #define IN_FILE    "gnuan.in"
  63. #define PROG_FILE  "gnuan.prog"
  64.  
  65.  
  66. #include <ctype.h>
  67. #include <signal.h>
  68. #include <fcntl.h>
  69. #include <time.h>
  70. #ifdef MSDOS
  71. #include <dos.h>
  72. #include <conio.h>
  73. #include <stdlib.h>
  74. #include <string.h>
  75. #include <io.h>
  76. #else
  77. #include <sys/param.h>
  78. #include <sys/types.h>
  79. #include <sys/file.h>
  80. #include <sys/ioctl.h>
  81. void TerminateSearch (int), Die (int);
  82. #define O_BINARY 0
  83.  
  84. #endif /* MSDOS */
  85.  
  86. #include "gnuchess.h"
  87. #include "ataks.h"
  88. #undef rxx
  89. #undef cxx
  90. #undef scanz
  91. #undef printz
  92.  
  93. #define rxx "12345678"
  94. #define cxx "abcdefgh"
  95. #define scanz scanf
  96. #define printz printf
  97.  
  98. char mvstr[4][6];
  99. extern char *ColorStr[2];
  100. int mycnt1, mycnt2;
  101.  
  102. static FILE *fpin;
  103. static FILE *fpout;
  104. int samedepth = false;
  105. char *DRAW;
  106. unsigned short int MV[MAXDEPTH];
  107. enum
  108. {
  109.   XBOARD, GNUCHESS, OTHER
  110. } InFileType;
  111. char InBuf[256];
  112.  
  113. #ifdef BACKGROUND_ANALYSIS
  114. static FILE *fpprog;
  115.  
  116. #endif
  117. static char white_actual_move[20];
  118. static char black_actual_move[20];
  119. static char white_suggest_move[20];
  120. static char black_suggest_move[20];
  121. static int sdw,sdb;
  122. static int white_score;
  123. static int black_score;
  124. int tmpscore;
  125. static int white_moving;
  126. static int current_depth;
  127. static int current_score;
  128. static int enable_update_display = 0;
  129.   int move_number = 1;
  130.  
  131. int CheckBook (short int side, char *s);
  132.  
  133. void
  134. Initialize (void)
  135. {
  136.   mycnt1 = mycnt2 = 0;
  137. }
  138.  
  139. void
  140. ExitChess (void)
  141. {
  142.   ListGame ();
  143.   exit (0);
  144. }
  145.  
  146. #ifndef MSDOS            /* never called!!! */
  147. void
  148. Die (int sig)
  149. {
  150.   ExitChess ();
  151. }
  152.  
  153. #endif /* MSDOS */
  154.  
  155. void
  156. TerminateSearch (int sig)
  157. {
  158. #ifdef MSDOS
  159.   sig++;            /* shut up the compiler */
  160. #endif /* MSDOS */
  161.   if (!flag.timeout)
  162.     flag.musttimeout = true;
  163.   flag.bothsides = false;
  164. }
  165.  
  166. void
  167. algbr (short int f, short int t, short int flag)
  168.  
  169. /*
  170.  * Generate move strings in different formats.
  171.  */
  172.  
  173. {
  174.   int m3p;
  175.  
  176.   if (f != t)
  177.     {
  178.       /* algebraic notation */
  179.       mvstr[0][0] = cxx[column (f)];
  180.       mvstr[0][1] = rxx[row (f)];
  181.       mvstr[0][2] = cxx[column (t)];
  182.       mvstr[0][3] = rxx[row (t)];
  183.       mvstr[0][4] = mvstr[3][0] = '\0';
  184.       if (((mvstr[1][0] = pxx[board[f]]) == 'P') || (flag & promote))
  185.     {
  186.       if (mvstr[0][0] == mvstr[0][2])    /* pawn did not eat */
  187.         {
  188.           mvstr[2][0] = mvstr[1][0] = mvstr[0][2];    /* to column */
  189.           mvstr[2][1] = mvstr[1][1] = mvstr[0][3];    /* to row */
  190.           m3p = 2;
  191.         }
  192.       else
  193.         /* pawn ate */
  194.         {
  195.           mvstr[2][0] = mvstr[1][0] = mvstr[0][0];    /* from column */
  196.           mvstr[2][1] = mvstr[1][1] = mvstr[0][2];    /* to column */
  197.           mvstr[2][2] = mvstr[0][3];
  198.           m3p = 3;        /* to row */
  199.         }
  200.       mvstr[2][m3p] = mvstr[1][2] = '\0';
  201.       if (flag & promote)
  202.         {
  203.           mvstr[0][4] = mvstr[1][2] = mvstr[2][m3p] = qxx[flag & pmask];
  204.           mvstr[1][3] = mvstr[2][m3p + 1] = mvstr[0][5] = '\0';
  205.         }
  206.     }
  207.       else
  208.     /* not a pawn */
  209.     {
  210.       mvstr[2][0] = mvstr[1][0];
  211.       mvstr[2][1] = mvstr[0][1];
  212.       mvstr[2][2] = mvstr[1][1] = mvstr[0][2];    /* to column */
  213.       mvstr[2][3] = mvstr[1][2] = mvstr[0][3];    /* to row */
  214.       mvstr[2][4] = mvstr[1][3] = '\0';
  215.       strcpy (mvstr[3], mvstr[2]);
  216.       mvstr[3][1] = mvstr[0][0];
  217.       if (flag & cstlmask)
  218.         {
  219.           if (t > f)
  220.         {
  221.           strcpy (mvstr[1], "o-o");
  222.           strcpy (mvstr[2], "O-O");
  223.         }
  224.           else
  225.         {
  226.           strcpy (mvstr[1], "o-o-o");
  227.           strcpy (mvstr[2], "O-O-O");
  228.         }
  229.         }
  230.     }
  231.     }
  232.   else
  233.     mvstr[0][0] = mvstr[1][0] = mvstr[2][0] = mvstr[3][0] = '\0';
  234. }
  235.  
  236.  
  237. int
  238. VerifyMove (char *s, short int iop, unsigned short int *mv)
  239.  
  240. /*
  241.  * Compare the string 's' to the list of legal moves available for the
  242.  * opponent. If a match is found, make the move on the board.
  243.  */
  244.  
  245. {
  246.   static short pnt, tempb, tempc, tempsf, tempst, cnt;
  247.   static struct leaf xnode;
  248.   struct leaf *node;
  249.  
  250.   *mv = 0;
  251.   if (iop == 2)
  252.     {
  253.       UnmakeMove (opponent, &xnode, &tempb, &tempc, &tempsf, &tempst);
  254.       return (false);
  255.     }
  256.   cnt = 0;
  257.   MoveList (opponent, 2);
  258.   pnt = TrPnt[2];
  259.   while (pnt < TrPnt[3])
  260.     {
  261.       node = &Tree[pnt++];
  262.       algbr (node->f, node->t, (short) node->flags);
  263.       if (strcmp (s, mvstr[0]) == 0 || strcmp (s, mvstr[1]) == 0 ||
  264.       strcmp (s, mvstr[2]) == 0 || strcmp (s, mvstr[3]) == 0)
  265.     {
  266.       cnt++;
  267.       xnode = *node;
  268.     }
  269.     }
  270.   if (cnt == 1)
  271.     {
  272.       MakeMove (opponent, &xnode, &tempb, &tempc, &tempsf, &tempst, &INCscore);
  273.       if (SqAtakd (PieceList[opponent][0], computer))
  274.     {
  275.       UnmakeMove (opponent, &xnode, &tempb, &tempc, &tempsf, &tempst);
  276.       printz ("Illegal move\n");
  277.       return (false);
  278.     }
  279.       else
  280.     {
  281.       if (iop == 1)
  282.         return (true);
  283.  
  284.       /*
  285.            * UpdateDisplay (xnode.f, xnode.t, 0, (short) xnode.flags);
  286.            */
  287.       if ((board[xnode.t] == pawn)
  288.           || (xnode.flags & capture)
  289.           || (xnode.flags & cstlmask))
  290.         {
  291.           Game50 = GameCnt;
  292.           ZeroRPT ();
  293.         }
  294.       GameList[GameCnt].depth = GameList[GameCnt].score = 0;
  295.       GameList[GameCnt].nodes = 0;
  296.       ElapsedTime (1);
  297.       GameList[GameCnt].time = (short) et;
  298.       TimeControl.clock[opponent] -= et;
  299.       --TimeControl.moves[opponent];
  300.       *mv = (xnode.f << 8) | xnode.t;
  301.       algbr (xnode.f, xnode.t, false);
  302.       return (true);
  303.     }
  304.     }
  305. #ifdef CHESSTOOL
  306.   printz ("Illegal move\n");
  307. #else
  308.   if (cnt > 1)
  309.     ShowMessage ("Ambiguous Move!");
  310. #endif
  311. if(cnt == 0){
  312.  pnt = TrPnt[2];
  313.   while (pnt < TrPnt[3])
  314.     {
  315.       node = &Tree[pnt++];
  316.       algbr (node->f, node->t, (short) node->flags);
  317.       printf("%s -> %s\n",s,mvstr[0]);
  318.     }
  319.   }
  320.   return (false);
  321. }
  322.  
  323. void
  324. help (void)
  325. {
  326. }
  327.  
  328. void
  329. EditBoard (void)
  330.  
  331. /*
  332.  * Set up a board position. Pieces are entered by typing the piece followed
  333.  * by the location. For example, Nf3 will place a knight on square f3.
  334.  */
  335.  
  336. {
  337. }
  338.  
  339. void
  340. SetupBoard (void)
  341.  
  342. /*
  343.  * Compatibility with Unix chess and the nchesstool. Set up a board position.
  344.  * Eight lines of eight characters are used to setup the board. a8-h8 is the
  345.  * first line. Black pieces are  represented  by  uppercase characters.
  346.  */
  347.  
  348. {
  349. }
  350.  
  351. void
  352. ShowDepth (char ch)
  353. {
  354. #ifdef MSDOS
  355.   ch++;                /* shut up the compiler */
  356. #endif /* MSDOS */
  357. }
  358.  
  359. void
  360. ShowLine (short unsigned int *bstline)
  361. {
  362.   register int i;
  363.  
  364.   for (i = 1; bstline[i] > 0; i++)
  365.     {
  366.       if ((i > 1) && (i % 8 == 1))
  367.     printf ("\n                          ");
  368.       algbr ((short) (bstline[i] >> 8), (short) (bstline[i] & 0xFF), false);
  369.       printf ("%5s ", mvstr[0]);
  370.     }
  371.   printf ("\n");
  372. }
  373.  
  374.  
  375. void
  376. ShowResults (short int score, unsigned short int *bstline, char ch)
  377. {
  378.   int i;
  379.  
  380.   if (flag.post)
  381.     {
  382.       ElapsedTime (2);
  383.       printf ("%2d%c %6d %4ld %8ld  ", Sdepth, ch, score, et / 100, NodeCnt);
  384.       ShowLine (bstline);
  385.     }
  386.   current_score = score;
  387.   current_depth = Sdepth;
  388.   for (i = 1; bstline[i] > 0; i++)
  389.     {
  390.       MV[i] = bstline[i];
  391.     } MV[i] = 0;
  392. }
  393.  
  394. void
  395. SearchStartStuff (short int side)
  396. {
  397.   signal (SIGINT, TerminateSearch);
  398. #ifndef MSDOS
  399.   signal (SIGQUIT, TerminateSearch);
  400. #endif /* MSDOS */
  401.   if (flag.post)
  402.     {
  403.       fprintf (stderr, "\nMove# %d    Target= %ld    Clock: %ld\n",
  404.            move_number,
  405.            ResponseTime, TimeControl.clock[side]);
  406.     }
  407. }
  408.  
  409. void
  410. OutputMove (void)
  411. {
  412.   if (white_moving)
  413.     {
  414.       strcpy (white_suggest_move, mvstr[0]);
  415.       white_score = current_score;
  416.     }
  417.   else
  418.     {
  419.       strcpy (black_suggest_move, mvstr[0]);
  420.       black_score = current_score;
  421.     }
  422. }
  423.  
  424.  
  425. #ifdef HASGETTIMEOFDAY
  426. #include <sys/time.h>
  427. void
  428. ElapsedTime (short int iop)
  429.  
  430.  
  431. /*
  432.  * Determine the time that has passed since the search was started. If the
  433.  * elapsed time exceeds the target (ResponseTime+ExtraTime) then set timeout
  434.  * to true which will terminate the search. iop = 0 calculate et bump ETnodes
  435.  * iop = 1 calculate et set timeout if time exceeded, calculate et
  436.  */
  437.  
  438. {
  439. struct timeval tv;
  440. #ifndef MSDOS
  441.   int nchar;
  442.   extern int errno;
  443.   int i;
  444. #ifdef FIONREAD
  445.   if (i = ioctl ((int) 0, FIONREAD, &nchar))
  446.     {
  447.       perror ("FIONREAD");
  448.       fprintf (stderr,
  449.         "You probably have a non-ANSI <ioctl.h>; see README. %d %d %x\n",
  450.     i, errno, FIONREAD);
  451.       exit (1);
  452.     }
  453.  
  454.   if (nchar)
  455.     {
  456.       if (!flag.timeout)
  457.     flag.back = true;
  458.       flag.bothsides = false;
  459.     }
  460. #endif /*FIONREAD*/
  461. #else
  462.   if (kbhit ())
  463.     {
  464.       if (!flag.timeout)
  465.     flag.back = true;
  466.       flag.bothsides = false;
  467.     }
  468. #endif /* MSDOS */
  469.   gettimeofday(&tv,NULL);
  470.   et = (tv.tv_sec*100+(tv.tv_usec/10000)) - time0;
  471.   ETnodes = NodeCnt + ZNODES;
  472.   if (et < 0)
  473.     et = 0;
  474.   if (iop == 1)
  475.     {
  476.       if (et > ResponseTime + ExtraTime && Sdepth > MINDEPTH)
  477.     flag.timeout = true;
  478.       ETnodes = NodeCnt + ZNODES;
  479.       gettimeofday(&tv,NULL);
  480.       time0 = tv.tv_sec*100+tv.tv_usec/10000;
  481.     }
  482. }
  483. #else
  484. void
  485. ElapsedTime (short int iop)
  486.  
  487.  
  488. /*
  489.  * Determine the time that has passed since the search was started. If the
  490.  * elapsed time exceeds the target (ResponseTime+ExtraTime) then set timeout
  491.  * to true which will terminate the search. iop = 0 calculate et bump ETnodes
  492.  * iop = 1 calculate et set timeout if time exceeded, calculate et
  493.  */
  494.  
  495. {
  496. #ifndef MSDOS
  497.   int nchar;
  498.   extern int errno;
  499.   int i;
  500. #ifdef FIONREAD
  501.   if (i = ioctl ((int) 0, FIONREAD, &nchar))
  502.     {
  503.       perror ("FIONREAD");
  504.       fprintf (stderr,
  505.         "You probably have a non-ANSI <ioctl.h>; see README. %d %d %x\n",
  506.     i, errno, FIONREAD);
  507.       exit (1);
  508.     }
  509.  
  510.   if (nchar)
  511.     {
  512.       if (!flag.timeout)
  513.     flag.back = true;
  514.       flag.bothsides = false;
  515.     }
  516. #endif /*FIONREAD*/
  517. #else
  518.   if (kbhit ())
  519.     {
  520.       if (!flag.timeout)
  521.     flag.back = true;
  522.       flag.bothsides = false;
  523.     }
  524. #endif /* MSDOS */
  525.   et = (time ((long *) 0) - time0) * 100;
  526.   ETnodes = NodeCnt + ZNODES;
  527.   if (et < 0)
  528.     et = 0;
  529.   if (iop == 1)
  530.     {
  531.       if (et > ResponseTime + ExtraTime && Sdepth > MINDEPTH)
  532.     flag.timeout = true;
  533.       ETnodes = NodeCnt + ZNODES;
  534.       time0 = time ((long *) 0);
  535.     }
  536. }
  537. #endif
  538. #ifdef notdef
  539. void
  540. ElapsedTime (short int iop)
  541.  
  542. /*
  543.  * Determine the time that has passed since the search was started. If the
  544.  * elapsed time exceeds the target (ResponseTime+ExtraTime) then set timeout
  545.  * to true which will terminate the search.
  546.  */
  547. {
  548.   et = (time ((long *) 0) - time0) * 100; 
  549. /*  et = (clock ()/CLOCKS_PER_SEC - time0) * 100;*/
  550.   if (et < 0)
  551.     et = 0;
  552.   ETnodes += ZNODES;
  553.   if (iop == 1)
  554.     {
  555.       if (et > ResponseTime + ExtraTime && Sdepth > 1)
  556.     flag.timeout = true;
  557.         time0 = time ((long *) 0); 
  558. /*      time0 = clock () / CLOCKS_PER_SEC;*/
  559.       ETnodes = NodeCnt + ZNODES;
  560.     }
  561. }
  562. #endif
  563.  
  564. void
  565. SetTimeControl (void)
  566. {
  567.   if (TCflag)
  568.     {
  569.       TimeControl.moves[white] = TimeControl.moves[black] = TCmoves;
  570.       TimeControl.clock[white] = TimeControl.clock[black] = 6000L * TCminutes;
  571.     }
  572.   else
  573.     {
  574.       TimeControl.moves[white] = TimeControl.moves[black] = 0;
  575.       TimeControl.clock[white] = TimeControl.clock[black] = 0;
  576.       MaxResponseTime = 6000L * TCminutes;
  577.     }
  578.   et = 0;
  579.   ElapsedTime (1);
  580. }
  581.  
  582. void
  583. ClrScreen (void)
  584. {
  585. #ifndef CHESSTOOL
  586.   printz ("\n");
  587. #endif
  588. }
  589.  
  590. void
  591. UpdateDisplay (short int f, short int t, short int redraw, short int isspec)
  592. {
  593. #ifndef CHESSTOOL
  594.   short r, c, l;
  595.  
  596.   if (!enable_update_display)
  597.     return;
  598.   if (redraw)
  599.     {
  600.       fprintf (fpout, "\n");
  601.       for (r = 7; r >= 0; r--)
  602.     {
  603.       for (c = 0; c <= 7; c++)
  604.         {
  605.           l = locn (r, c);
  606.           if (color[l] == neutral)
  607.         fprintf (fpout, " -");
  608.           else if (color[l] == white)
  609.         fprintf (fpout, " %c", qxx[board[l]]);
  610.           else
  611.         fprintf (fpout, " %c", pxx[board[l]]);
  612.         }
  613.       fprintf (fpout, "\n");
  614.     }
  615.       fprintf (fpout, "\n");
  616.     }
  617. #endif /* CHESSTOOL */
  618. #ifdef MSDOS
  619.   f++;
  620.   t++;
  621.   isspec++;            /* shut up the compiler */
  622. #endif /* MSDOS */
  623. }
  624.  
  625. void
  626. GetGame (void)
  627. {
  628. }
  629.  
  630. void
  631. SaveGame (void)
  632. {
  633. }
  634.  
  635. void
  636. ListGame (void)
  637. {
  638. }
  639.  
  640. void
  641. Undo (void)
  642.  
  643. /*
  644.  * Undo the most recent half-move.
  645.  */
  646.  
  647. {
  648.   short f, t;
  649.   f = GameList[GameCnt].gmove >> 8;
  650.   t = GameList[GameCnt].gmove & 0xFF;
  651.   if (board[t] == king && distance (t, f) > 1)
  652.     (void) castle (GameList[GameCnt].color, f, t, 2);
  653.   else
  654.     { 
  655.       /* Check for promotion: */
  656.       if (GameList[GameCnt].flags & promote)
  657.         {
  658.           board[t] = pawn;
  659.         } 
  660.       board[f] = board[t];
  661.       color[f] = color[t];
  662.       board[t] = GameList[GameCnt].piece;
  663.       color[t] = GameList[GameCnt].color;
  664.       if (color[t] != neutral)
  665.         Mvboard[t]--;
  666.       Mvboard[f]--;
  667.     } 
  668.   if (GameList[GameCnt].flags & epmask)
  669.     EnPassant (otherside[color[f]], f, t, 2);
  670.   else
  671.     InitializeStats ();
  672. epsquare = GameList[GameCnt].epssq;
  673.   if (TCflag && (TCmoves>1))
  674.     ++TimeControl.moves[color[f]];
  675.   hashkey = GameList[GameCnt].hashkey;
  676.   hashbd = GameList[GameCnt].hashbd;
  677.   GameCnt--;
  678.   computer = computer ^ 1;
  679.   opponent = opponent ^ 1;
  680.   flag.mate = false;
  681.   Sdepth = 0;
  682.   player = player ^ 1;
  683. /*
  684.   ShowSidetoMove ();
  685.   UpdateDisplay (0, 0, 1, 0);
  686. */
  687.   if (flag.regularstart)
  688.     Book = BOOKFAIL;
  689. }
  690.  
  691. #ifdef notdef
  692. void
  693. Undo (void)
  694.  
  695. /*
  696.  * Undo the most recent half-move.
  697.  */
  698.  
  699. {
  700.   short f, t;
  701.  
  702.   f = GameList[GameCnt].gmove >> 8;
  703.   t = GameList[GameCnt].gmove & 0xFF;
  704.   if (board[t] == king && distance (t, f) > 1)
  705.     (void) castle (GameList[GameCnt].color, f, t, 2);
  706.   else
  707.     {
  708.       /* Check for promotion: */
  709.       if (GameList[GameCnt].flags & promote)
  710.     {
  711.       board[t] = pawn;
  712.     }
  713.       board[f] = board[t];
  714.       color[f] = color[t];
  715.       board[t] = GameList[GameCnt].piece;
  716.       color[t] = GameList[GameCnt].color;
  717.       if (color[t] != neutral)
  718.     Mvboard[t]--;
  719.       Mvboard[f]--;
  720.     }
  721.   if (GameList[GameCnt].flags & epmask)
  722.     EnPassant (color[t], f, t, 2);
  723.   if (TCflag)
  724.     ++TimeControl.moves[color[f]];
  725.   GameCnt--;
  726.   computer = otherside[computer];
  727.   opponent = otherside[opponent];
  728.   flag.mate = false;
  729.   Sdepth = 0;
  730.   InitializeStats ();
  731. }
  732.  
  733. #endif
  734. void
  735. ShowMessage (char *s)
  736. {
  737.   fprintf (stderr, "%s\n", s);
  738. }
  739.  
  740. void
  741. ShowSidetoMove (void)
  742. {
  743. }
  744.  
  745. void
  746. PromptForMove (void)
  747. {
  748. #ifndef CHESSTOOL
  749.   printz ("\nYour move is? ");
  750. #endif /* CHESSTOOL */
  751. }
  752.  
  753.  
  754. void
  755. ShowCurrentMove (short int pnt, short int f, short int t)
  756. {
  757. #ifdef MSDOS
  758.   f++;
  759.   t++;
  760.   pnt++;            /* shut up the compiler */
  761. #endif /* MSDOS */
  762. }
  763.  
  764. void
  765. ChangeAlphaWindow (void)
  766. {
  767.   printz ("window: ");
  768. }
  769.  
  770. void
  771. ChangeBetaWindow (void)
  772. {
  773.   printz ("window: ");
  774. }
  775.  
  776. void
  777. GiveHint (void)
  778. {
  779.   algbr ((short) (hint >> 8), (short) (hint & 0xFF), false);
  780.   fprintf (stderr, "Hint: %s\n", mvstr[0]);
  781. }
  782.  
  783. void
  784. SelectLevel (char *sx)
  785. {
  786. }
  787.  
  788. void
  789. ChangeSearchDepth (void)
  790. {
  791.   printz ("depth= ");
  792.   scanz ("%hd", &MaxSearchDepth);
  793. }
  794.  
  795. void
  796. SetContempt (void)
  797. {
  798.   printz ("contempt= ");
  799.   scanz ("%hd", &contempt);
  800. }
  801.  
  802. void
  803. ChangeXwindow (void)
  804. {
  805.   printz ("xwndw= ");
  806.   scanz ("%hd", &xwndw);
  807. }
  808.  
  809. void
  810. TestSpeed (void (*f) (short int side, short int ply))
  811. {
  812.   short i;
  813.   long cnt, rate, t1, t2;
  814.  
  815.   t1 = time (0);
  816.   for (i = 0; i < 10000; i++)
  817.     {
  818.       f (opponent, 2);
  819.     }
  820.   t2 = time (0);
  821.   cnt = 10000L * (TrPnt[3] - TrPnt[2]);
  822.   rate = cnt / (t2 - t1);
  823.   printz ("Nodes= %ld Nodes/sec= %ld\n", cnt, rate);
  824. }
  825.  
  826. int
  827. GetNextMove (char *buffer)
  828. {
  829.   char cbuf[128];
  830. char sdepth[128];
  831. int sdindex;
  832.   char *p,*q;
  833.   sdw = sdb =0;
  834.   black_actual_move[0] = '\0';
  835.   white_actual_move[0] = '\0';
  836.   if(fgets(cbuf,sizeof(cbuf),fpin) != NULL){
  837.   p = cbuf;
  838.   for(;*p;p++){
  839.       if(isalpha(*p)){
  840.         q = white_actual_move;
  841.                 while(*p != ' ' && *p != '\n') *q++ = *p++;
  842.                         *q = '\0';
  843.     if(strcmp(white_actual_move,"Book")==0) continue; else break;
  844. break;
  845.       }
  846.   }
  847.   if(*p == '\0' && white_actual_move[0] == '\0')return 0;
  848.   if(InFileType == GNUCHESS){
  849.   if(samedepth){
  850.       sdindex = 0;
  851.       while (*p == ' ' || *p == '\n') p++;
  852.       while (*p != ' ' && *p != '\0') p++;
  853.       while (*p  == ' ' || *p == '\n')p++;
  854.     while (*p != ' ' && *p != '\n') sdepth[sdindex++] = *p++;
  855.     sdepth[sdindex] = '\0';
  856.     if(strcmp(sdepth,"Book")==0){sdw = -99;for(;*p!=' ';p++);}
  857.     else sdw = atoi(sdepth);
  858.     }
  859.   }
  860.  
  861.   for(;*p;p++){
  862.   if(isalpha(*p)){
  863.     q = black_actual_move;
  864.         while(*p != ' ' && *p != '\n') *q++ = *p++;
  865.     *q = '\0';
  866.     if(strcmp(black_actual_move,"Book")==0) continue; else break;
  867.   }
  868.   }
  869.   if(*p == '\0' && black_actual_move[0] == '\0')return 1;
  870.   if(InFileType == GNUCHESS){
  871. if(samedepth){
  872.     sdindex = 0;
  873.       while (*p == ' ' || *p == '\n') p++;
  874.       while (*p != ' ' && *p != '\0') p++;
  875.       while (*p  == ' ' || *p == '\n')p++;
  876.     while (*p != ' ' && *p != '\n') sdepth[sdindex++] = *p++;
  877.     sdepth[sdindex] = '\0';
  878.     if(strcmp(sdepth,"Book")==0){sdb = -99;for(;*p!=' ';p++);}
  879.     else sdb = atoi(sdepth);
  880.     }
  881.   }
  882.  
  883.   return 1;
  884.   } else /* EOF */
  885.   return -1;
  886.  
  887. }
  888.  
  889. void
  890. InputCommand (void)
  891.  
  892. /*
  893.  * Open the file of moves to analyse.  Go through the file move by move and
  894.  * do the following for each move.  See what gnuchess would have done in that
  895.  * position.  Record the move it would have made along with the score it
  896.  * would have given and the search depth.  Take back its move. Force the move
  897.  * that was actually made.  Keep track of statistics such as how many moves
  898.  * agreed.
  899.  */
  900.  
  901. {
  902.   int i;
  903.   short ok, inbook;
  904.   unsigned short mv;
  905.   char s[80];
  906.   int search_depth;
  907. #if !defined BACKGROUND_ANALYSIS
  908.   int max_minutes;
  909.   int max_seconds;
  910.   char inbuf[256];
  911. #else
  912.   char outfilename[255];
  913.   char progfilename[255];
  914. #endif
  915.   char infilename[255];
  916.   long start_time, end_time, elapsed_time;
  917.   int total_black_moves, total_white_moves;
  918.   int same_black_moves, same_white_moves;
  919.   float white_percent, black_percent;
  920.  
  921.   /* Initialize necessary variables. */
  922.  
  923.   flag.quit = false;
  924.   flag.beep = false;
  925.   flag.post = true;
  926.   player = opponent;
  927.   enable_update_display = 1;
  928.   ft = 0;
  929.   Book = false;
  930.   total_black_moves = 0;
  931.   total_white_moves = 0;
  932.   same_black_moves = 0;
  933.   same_white_moves = 0;
  934.  
  935. #ifdef BACKGROUND_ANALYSIS
  936.  
  937.   /*
  938.    * Set the in files to standard ones for analysis if background
  939.    * processing selected.
  940.    */
  941.  
  942.   strcpy (infilename, IN_FILE);
  943.   strcpy (outfilename, OUT_FILE);
  944.   strcpy (progfilename, PROG_FILE);
  945.   fpout = fopen (outfilename, "w");
  946.   if (fpout == NULL)
  947.     {
  948.       fprintf (fpout, "This file does not exist : %s\n", outfilename);
  949.       flag.quit = 1;
  950.       return;
  951.     }
  952.   MaxSearchDepth = search_depth = MAX_DEPTH;
  953.   TCminutes = MAX_TIME;
  954.  
  955. #else
  956.  
  957.   /* Request information on where the file is and the depth an time. */
  958.  
  959.   fpout = stderr;
  960.   fprintf (fpout, "Input the file with the algebraic moves of the game.\n");
  961.   fflush(fpout);
  962.   gets (infilename);
  963.   fprintf (fpout, "\n");
  964.   do
  965.     {
  966.       fprintf (fpout, "Input the search depth you want to use.  (1 to 29)(- for depth from file)\n");
  967.       gets (inbuf);
  968.       search_depth = atoi (inbuf);
  969.       if(search_depth < 0) {samedepth = true; search_depth = -search_depth;}
  970.   } while (search_depth < 1 || search_depth > 29);
  971.   MaxSearchDepth = search_depth;
  972.  
  973.   fprintf (fpout, "\n");
  974.       max_minutes = max_seconds = 0;
  975.   do
  976.     {
  977.       fprintf (fpout, "Input the maximum number of minutes per move you want to use.\n");
  978.       gets (inbuf);
  979.       max_minutes = atoi (inbuf);
  980.       if(max_minutes < 0){max_seconds = -max_minutes;max_minutes=0;}
  981.   } while ((max_minutes+max_seconds) < 1);
  982.   printf ("\nYou will search to %d half moves\n", search_depth);
  983.   printf ("\nWith no search taking more than %d minutes\n",max_minutes);
  984.   TCminutes = max_minutes;
  985.  
  986.   fprintf (fpout, "\n\n");
  987.  
  988. #endif
  989.  
  990.   fpin = fopen (infilename, "r");
  991.   if (fpin == NULL)
  992.     {
  993.       fprintf (fpout, "This file does not exist : %s\n", infilename);
  994.       flag.quit = 1;
  995.       return;
  996.     }
  997.   /* lets find out about this file */
  998.   fgets (InBuf, 256, fpin);
  999.   InFileType = OTHER;
  1000.   if (!strncmp (InBuf, "xboard", 6))
  1001.     {
  1002.       InFileType = XBOARD;
  1003.       fgets (InBuf, 256, fpin);
  1004.       fgets (InBuf, 256, fpin);
  1005.     }
  1006.   else if (!strncmp (InBuf, "gnuchess", 6))
  1007.     {
  1008.       InFileType = GNUCHESS;
  1009.       fgets (InBuf, 256, fpin);
  1010.     }
  1011.   else
  1012.     rewind (fpin);
  1013.   TCmoves = 1;
  1014.   TCflag = (TCmoves > 1);
  1015. /*  flag.onemove = true; */
  1016.   OperatorTime = 0;
  1017.   SetTimeControl ();
  1018.  
  1019.  
  1020.   fprintf (fpout, "Move White Black      Score Depth     Best Line\n");
  1021.   fprintf (fpout, "------------------------------------------------------------------\n");
  1022.  
  1023. #ifdef BACKGROUND_ANALYSIS
  1024.  
  1025.   /*
  1026.    * Update progress in the progress file if this is running in the
  1027.    * background.
  1028.    */
  1029.  
  1030.   fpprog = fopen (progfilename, "w");
  1031.   fprintf (fpprog, "Done with move #%d.\n", move_number - 1);
  1032.   fclose (fpprog);
  1033.  
  1034. #endif
  1035.  
  1036.   time (&start_time);
  1037.   while (1)
  1038.     {
  1039.       opponent = black;
  1040.       computer = white;
  1041.       player = computer;
  1042.       white_moving = 1;
  1043.       if (!GetNextMove (s))
  1044.     {
  1045.       flag.quit = 1;
  1046.       break;
  1047.     }
  1048.     if(sdw == -99) MaxSearchDepth = search_depth; else
  1049.       MaxSearchDepth = (sdw)?sdw:search_depth;
  1050.       if (!strcmp (white_actual_move, "Black") || !strcmp (white_actual_move, "White") || !strcmp (white_actual_move, "draw"))
  1051.     break;
  1052.       inbook = CheckBook (white, white_actual_move);
  1053.       if (!inbook)
  1054.         {
  1055.           flag.force = 0;
  1056.           SelectMove (computer, 1);
  1057.           Undo ();
  1058.           SetTimeControl ();  
  1059.           flag.force = 1;
  1060.         }
  1061.       opponent = white;
  1062.       computer = black;
  1063.       player = opponent;
  1064.       ok = VerifyMove (white_actual_move, 0, &mv);
  1065. #ifdef notdef
  1066.   ExaminePosition ();
  1067.   tmpscore = ScorePosition (white);
  1068. #endif
  1069.       if (!ok)
  1070.     {
  1071.           fprintf (fpout, "\nBad move.  %s  Board position is: \n", white_actual_move);
  1072.       UpdateDisplay (0, 0, 1, 0);
  1073.       flag.quit = 1;
  1074.       break;
  1075.     }
  1076.       else if (inbook)
  1077.         {
  1078.           fprintf (fpout, "%3d   %-9s         -     -    book\n", move_number,white_actual_move);
  1079.           fflush (fpout);
  1080.           move_number++;
  1081.           Sdepth = 0;
  1082.           ft = 0;
  1083.         }
  1084.       else
  1085.     {
  1086.       char  x[80];
  1087.       strcpy (x, white_actual_move);
  1088.       if (strcmp (white_actual_move, white_suggest_move))
  1089.         strcat (x, "*");
  1090. #ifdef notdef
  1091.       fprintf (fpout, "%3d   %-9s      %5d%5d%5d   ", move_number, x,tmpscore, white_score, current_depth);
  1092. #endif
  1093.     if(sdw == -99)
  1094.       fprintf (fpout, "%3d   %-9s      %5d   Book ", move_number, x, white_score, current_depth);
  1095.     else
  1096.       fprintf (fpout, "%3d   %-9s      %5d%5d   ", move_number, x, white_score, current_depth);
  1097.       for (i = 1; MV[i] > 0; i++)
  1098.         {
  1099.           algbr ((short) (MV[i] >> 8), (short) (MV[i] & 0xFF), false);
  1100.           fprintf (fpout,"%5s ", mvstr[0]);
  1101.         }
  1102.       fprintf (fpout,"\n");
  1103.       fflush (fpout);
  1104.       move_number++;
  1105.       total_white_moves++;
  1106.       if (!strcmp (white_actual_move, white_suggest_move))
  1107.         same_white_moves++;
  1108.       Sdepth = 0;
  1109.       ft = 0;
  1110.     }
  1111.       player = computer;
  1112.       white_moving = 0;
  1113.     if(sdb == -99) MaxSearchDepth = search_depth; else
  1114.       MaxSearchDepth = (sdb)?sdb:search_depth;
  1115.       if (!strcmp (black_actual_move, "Black") || !strcmp (black_actual_move, "White") || !strcmp (black_actual_move, "draw"))
  1116.     break;
  1117.       inbook = CheckBook (black, black_actual_move);
  1118.       if (!inbook)
  1119.         {
  1120.           flag.force = 0;
  1121.           SelectMove (computer, 1);
  1122.           Undo ();
  1123.           SetTimeControl ();
  1124.           flag.force = 1;
  1125.         }
  1126.       opponent = black;
  1127.       computer = white;
  1128.       player = opponent;
  1129.       ok = VerifyMove (black_actual_move, 0, &mv);
  1130. #ifdef notdef
  1131.   ExaminePosition ();
  1132.   tmpscore = ScorePosition (black);
  1133. #endif
  1134.       if (!ok)
  1135.     {
  1136.       fprintf (fpout, "\nBad move.  %s  Board position is: \n", s);
  1137.       UpdateDisplay (0, 0, 1, 0);
  1138.       flag.quit = 1;
  1139.       break;
  1140.     }
  1141.       else if (inbook)
  1142.         {
  1143.           fprintf (fpout, "            %-9s   -     -    book\n",black_actual_move);
  1144.           fflush (fpout);
  1145.           Sdepth = 0;
  1146.           ft = 0;
  1147.         }
  1148.       else
  1149.     {
  1150.       char x[8];
  1151.       strcpy (x, black_actual_move);
  1152.       if (strcmp (black_actual_move, black_suggest_move))
  1153.         strcat (x, "*");
  1154. #ifdef notdef
  1155.       fprintf (fpout, "            %-9s%5d%5d%5d   ", x,tmpscore, black_score, current_depth);
  1156. #endif
  1157.     if(sdb == -99)
  1158.       fprintf (fpout, "            %-9s%5d  Book  ", x, black_score, current_depth);
  1159.     else
  1160.       fprintf (fpout, "            %-9s%5d%5d   ", x, black_score, current_depth);
  1161.       for (i = 1; MV[i] > 0; i++)
  1162.         {
  1163.           algbr ((short) (MV[i] >> 8), (short) (MV[i] & 0xFF), false);
  1164.           fprintf (fpout,"%5s ", mvstr[0]);
  1165.         }
  1166.       fprintf (fpout,"\n");
  1167.       fflush (fpout);
  1168.       total_black_moves++;
  1169.       if (!strcmp (black_actual_move, black_suggest_move))
  1170.         same_black_moves++;
  1171.       Sdepth = 0;
  1172.       ft = 0;
  1173.     }
  1174.  
  1175. #ifdef BACKGROUND_ANALYSIS
  1176.  
  1177.         /*
  1178.          * Update progress in the progress file if this is running in the
  1179.          * background.
  1180.          */
  1181.  
  1182.         fpprog = fopen (progfilename, "w");
  1183.         fprintf (fpprog, "Done with move #%d.\n", move_number - 1);
  1184.         fclose (fpprog);
  1185. #else
  1186.  
  1187.         /*
  1188.          * fprintf(stderr, "Done with move #%d.\n", move_number-1);
  1189.          */
  1190.  
  1191. #endif
  1192.  
  1193.     }
  1194.  
  1195.   white_percent = ((float) same_white_moves) * 100 / (float) total_white_moves;
  1196.   black_percent = ((float) same_black_moves) * 100 / (float) total_black_moves;
  1197.   fprintf (fpout, "\n           White's percentage was %5.2f%%.     Black's percentage was %5.2f%%.\n", white_percent, black_percent);
  1198.   time (&end_time);
  1199.   elapsed_time = end_time - start_time;
  1200.   fprintf (fpout, "\n           Elapsed time was %d seconds.\n", elapsed_time);
  1201.   fclose (fpin);
  1202.   fclose (fpout);
  1203.   exit (0);
  1204. }
  1205.  
  1206.  
  1207. #ifdef GDM
  1208. int
  1209. CheckBook (short int side, char *s)
  1210. {
  1211.   return false;
  1212. }
  1213.  
  1214. #elif defined GDX
  1215. #ifdef LONG64
  1216. #define lts(x) (((x>>48)&0xfffe)|side)
  1217. #else
  1218. #define lts(x) (((x>>16)&0xfffe)|side)
  1219. #endif
  1220.  
  1221. int
  1222. CheckBook (short int side, char *s)
  1223. {
  1224. /*
  1225.  *  Check to see if the move in char *s can be found in the book.
  1226.  */
  1227.  
  1228. struct gdxadmin
  1229. {
  1230.     unsigned int bookcount;
  1231.     unsigned int booksize;
  1232.     unsigned long maxoffset;
  1233. } d;
  1234. struct gdxdata
  1235. {
  1236.     unsigned long hashbd;
  1237.     unsigned short hashkey;
  1238.     unsigned short bmove;
  1239.     unsigned short hint;
  1240.     unsigned short count;
  1241. } a;
  1242. unsigned long currentoffset;
  1243. int gfd = -1;
  1244. unsigned short m = 0;
  1245. char *binbookfile = BINBOOK;
  1246. unsigned long bhashkey, bhashbd;
  1247. short int flag;
  1248.  
  1249.  
  1250. bhashkey = hashkey;
  1251. bhashbd = hashbd;
  1252. if ((gfd = open (binbookfile, O_RDONLY | O_BINARY)) == -1) return false;
  1253. read (gfd, &d, sizeof (struct gdxadmin));
  1254. currentoffset = (unsigned long) (bhashkey % d.booksize) * sizeof (struct gdxdata) + sizeof (struct gdxadmin);
  1255. while (true)
  1256.   {
  1257.     lseek (gfd, currentoffset, SEEK_SET);
  1258.     if (read (gfd, &a, sizeof (struct gdxdata)) == 0) break;
  1259.     if (a.bmove == 0) break;
  1260.     if (a.hashkey == (unsigned short)(lts(bhashkey)) && a.hashbd == bhashbd)
  1261.       {
  1262.         m = a.bmove & (~LASTMOVE) & (~BADMOVE);
  1263.         flag = 0;
  1264.         if (toupper(s[0]) == 'O') flag |= cstlmask;     /*assume castling*/
  1265.         algbr (m >> 8, m & 0xFF, flag);
  1266.         if (strcmp (s, mvstr[0]) == 0 || strcmp (s, mvstr[1]) == 0 ||
  1267.             strcmp (s, mvstr[2]) == 0 || strcmp (s, mvstr[3]) == 0)
  1268.         return true;
  1269.       }
  1270.     currentoffset += sizeof (struct gdxdata);
  1271.     if (currentoffset > d.maxoffset)
  1272.       currentoffset = sizeof (struct gdxadmin);
  1273.   }
  1274.  
  1275.   return false;
  1276. }
  1277. #endif
  1278.